---
title: "useServerAction"
group: "Client Side Usage"
groupOrder: 0
---

`useServerAction` is a custom React hook provided by ZSA that allows you to easily execute server actions from your client components. It handles the execution, transition, loading states, optimistic updates, and error handling for you.

## Basic Example

```tsx title="increment-example.tsx"
"use client"

import { incrementNumberAction } from "./actions";
import { useServerAction } from "zsa-react";
import { useState } from "react";
import { Button, Card, CardContent, CardDescription, CardHeader, CardTitle } from "ui";

export default function IncrementExample() {
    const [counter, setCounter] = useState(0);
    const { isPending, execute, data, error, isError } = useServerAction(incrementNumberAction); // [!code highlight]

    return (
        <Card>
            <CardHeader>
                <CardTitle>Increment Number</CardTitle>
            </CardHeader>
            <CardContent className="flex flex-col gap-4">
                <Button
                  disabled={isPending}
                  onClick={async () => {
                      const [data, err] = await execute({ // [!code highlight]
                          number: counter, // [!code highlight]
                      }) // [!code highlight]

                      if (err) {
                          // handle error
                          return
                      }

                      setCounter(data);
                  }}
                >
                  Invoke action
                </Button>
                <p>Count:</p>
                <div>{isPending ? "saving..." : data}</div> // [!code highlight]
                {isError && error.code === "INPUT_PARSE_ERROR" && (
                  <div>{error.fieldErrors.number}</div>
                )}
            </CardContent>
        </Card>
    );
}
```

- `useServerAction` allows you to use this server action from within your client components.
- `execute` executes the server action endpoint with the typesafe input directly from `onClick`.

<Note>
useServerAction uses the useTransition hook internally to handle the transition state of the action
</Note>

Here is the result:

<ExampleComponent id="increment-example" />

## Usage

```tsx title="callbacks-example.tsx"
import { useServerAction } from "zsa-react"
import { myServerAction } from "./actions"

function MyComponent() {
  const {
    data,
    isPending,
    isOptimistic,
    isError,
    error,
    isSuccess,
    status,
    execute,
    setOptimistic,
    reset,
  } = useServerAction(myServerAction, {
    onError: ({ err }) => {
      console.error("Server action error:", err)
    },
    onSuccess: ({ data }) => {
      console.log("Server action success:", data)
    },
    onStart: () => {
      console.log("Server action started")
    },
    onFinish: ([data, err]) => {
      console.log("Server action finished (invoked after onError/onSuccess)")
    },
    initialData: {/* ... */},
    retry: {
      maxAttempts: 3,
      delay: 1000, // or (currentAttempt, err) => { /* ... */ }
    },
  })

  return (
    <div>
      <button onClick={() => execute({ /* input */ })}>Execute</button>
      {isPending && <div>Loading...</div>}
      {isError && <div>Error: {error.message}</div>}
      {isSuccess && <div>Data: {JSON.stringify(data)}</div>}
    </div>
  )
}
```

## Parameters

- `serverAction`: A server action created using `createServerAction`.
- `opts` (optional): An object containing additional options:
  - `onError`: A callback function to be called when the server action encounters an error. It receives an object with the `err` property containing the error.
  - `onSuccess`: A callback function to be called when the server action succeeds. It receives an object with the `data` property containing the returned data.
  - `onStart`: A callback function to be called when the server action starts executing.
  - `onFinish`: A callback function to be called when the server action finishes executing, regardless of the outcome.
  - `initialData`: Initial data to be used as the `data` value before the server action is executed.
  - `retry`: An object specifying the retry behavior:
    - `maxAttempts`: The maximum number of retry attempts.
    - `delay`: The delay in milliseconds between retry attempts, or a function that takes the current attempt number and error, and returns the delay.
  - `persistErrorWhilePending`: When you want to persist the error state while the server action is pending. Default is `false`.
  - `persistDataWhilePending`: When you want to persist the data state while the server action is pending. Default is `false`. This is helpful if you have form fields that you want to keep filled even when there is an error on other fields.


## Return Value

`useServerAction` returns an object with the following properties:

- `data`: The data returned by the server action, or `undefined` if the action hasn't completed successfully yet.
- `isPending`: A boolean indicating whether the server action is currently being executed.
- `isOptimistic`: A boolean indicating whether the `data` is an optimistic update.
- `isError`: A boolean indicating whether the server action encountered an error.
- `error`: The error object if the server action encountered an error, or `undefined` otherwise.
- `isSuccess`: A boolean indicating whether the server action completed successfully.
- `status`: The current status of the server action: `"idle"`, `"pending"`, `"success"`, or `"error"`.
- `execute`: A function to execute the server action with the provided input.
- `setOptimistic`: A function to set an optimistic update for the `data` value. It accepts either the new data directly or a function that receives the current data and returns the new data.
- `reset`: A function to reset the state of the server action to its initial values.

## Retry Behavior

`useServerAction` supports automatic retries when the server action encounters an error. You can configure the retry behavior using the `retry` option:

- `maxAttempts`: Specifies the maximum number of retry attempts. Default is no retries.
- `delay`: Specifies the delay in milliseconds between retry attempts. It can be a fixed number or a function that takes the current attempt number and error, and returns the delay. Default is no delay.

<Info>
The `retry` option is useful for handling temporary network issues or server errors that may resolve after a short delay.
</Info>

## Optimistic Updates

`useServerAction` allows you to set optimistic updates for the `data` value using the `setOptimistic` function. Optimistic updates let you update the UI immediately based on the expected outcome of the server action, providing a better user experience.

You can pass either the new data directly or a function that receives the current data and returns the new data to `setOptimistic`. If the server action fails, the optimistic update will be rolled back to the previous value.

## Form Actions

`useServerAction` also supports executing a form action directly. This is useful when you want to handle form submissions in your React components.

To do this, you can use the `executeFormAction` function passed back by `useServerAction` hook.

First, make sure you have the input type set to `"formData"` in your server action.

```typescript title="actions.ts"
"use server"

import z from "zod"
import { createServerAction } from "zsa"

export const produceNewMessage = createServerAction()
  .input(
    z.object({
      name: z.string().min(5),
    }),
    {
      type: "formData", // [!code highlight]
    }
  )
  .handler(async ({ input }) => {
    await new Promise((resolve) => setTimeout(resolve, 500))
    return "Hello, " + input.name
  })
```

Then, you can use the `executeFormAction` function to execute the form action.

```tsx title="form-example.tsx"
"use client"

import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { useServerAction } from "zsa-react"
import { produceNewMessage } from "./actions"

export const ExecuteFormAction = () => {
  const { isPending, executeFormAction, isSuccess, data, isError, error } = // [!code highlight]
    useServerAction(produceNewMessage) // [!code highlight]

  return (
    <Card className="not-prose">
      <CardHeader>
        <CardTitle>Form Example</CardTitle>
      </CardHeader>
      <CardContent className="flex flex-col gap-4">
        <form className="flex flex-col gap-4" action={executeFormAction}> // [!code highlight]
          <Input type="text" name="name" placeholder="Enter your name..." />
          <Button className="w-full" type="submit" disabled={isPending}>
            Submit
          </Button>
          {isPending && <div>Loading...</div>}
          {isSuccess && <div>Success: {JSON.stringify(data)}</div>}
          {isError && <div>Error: {JSON.stringify(error.fieldErrors)}</div>}
        </form>
      </CardContent>
    </Card>
  )
}
```

Here is the result:

<ExampleComponent id="execute-form-action" />

That's it! You can now use `useServerAction` to execute server actions and handle their results in your React components with ease.
